package com.chenfan.mcn.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.chenfan.common.exception.BusinessException;
import com.chenfan.common.vo.UserVO;
import com.chenfan.mcn.clients.privilege.PrivilegeClient;
import com.chenfan.mcn.clients.privilege.SDepartment;
import com.chenfan.mcn.clients.privilege.SUserVo;
import com.chenfan.mcn.config.UserVoContextHolder;
import com.chenfan.mcn.dao.DepartmentTargetMapper;
import com.chenfan.mcn.exception.McnErrorCode;
import com.chenfan.mcn.model.DepartmentTarget;
import com.chenfan.mcn.model.McnPage;
import com.chenfan.mcn.model.dto.DepartmentTargetDTO;
import com.chenfan.mcn.model.dto.DepartmentTargetSearchDTO;
import com.chenfan.mcn.model.vo.DepartmentTargetDetailVO;
import com.chenfan.mcn.model.vo.DepartmentTargetListVO;
import com.chenfan.mcn.model.vo.DepartmentTargetPageVO;
import com.chenfan.mcn.service.DepartmentTargetService;
import com.chenfan.mcn.utils.BusinessAssert;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author lizhejin
 * @since 2021-04-20
 */
@Service
public class DepartmentTargetServiceImpl extends ServiceImpl<DepartmentTargetMapper, DepartmentTarget> implements DepartmentTargetService {


    /**
     * 客户部
     */
    public static final long CUSTOM_DEPARTMENT_ID = 1355072169771536385L;

    @Autowired
    private PrivilegeClient privilegeClient;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Integer addTarget(List<DepartmentTargetDTO> departmentTargetList) {
        verifyInsertParam(departmentTargetList);
        verifyTargetCount(departmentTargetList);
        UserVO user = UserVoContextHolder.getUserVo();
        List<DepartmentTarget> departmentTargets = new ArrayList<>();
        for (DepartmentTargetDTO departmentTargetDTO : departmentTargetList) {
            DepartmentTarget departmentTarget = new DepartmentTarget();
            departmentTarget.setQuarterCode(departmentTargetDTO.getQuarterCode());
            departmentTarget.setTargetAmount(departmentTargetDTO.getTargetAmount());
            departmentTarget.setTargetDepartmentId(departmentTargetDTO.getTargetDepartmentId());
            departmentTargets.add(departmentTarget);
        }
        return baseMapper.insertBatch(departmentTargets);
    }

    @Override
    public DepartmentTargetDTO targetDetail(Long id) {
        DepartmentTarget departmentTarget = baseMapper.selectById(id);
        if (departmentTarget == null) {
            throw new BusinessException(McnErrorCode.DEPARTMENT_TARGET_NOT_EXIST);
        }
        DepartmentTargetDTO departmentTargetDTO = new DepartmentTargetDTO();
        BeanUtils.copyProperties(departmentTarget, departmentTargetDTO);
        Map<Long, SDepartment> departmentMap = privilegeClient.getDepartmentByIds(Arrays.asList(departmentTargetDTO.getTargetDepartmentId())).getObj();
        if (departmentMap.containsKey(departmentTargetDTO.getTargetDepartmentId())) {
            departmentTargetDTO.setTargetDepartmentName(departmentMap.get(departmentTargetDTO.getTargetDepartmentId()).getDepartmentName());
        }
        return departmentTargetDTO;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Integer deleteTarget(Long id) {
        DepartmentTarget entity = baseMapper.selectById(id);
        BusinessAssert.notNull(entity, McnErrorCode.DEPARTMENT_TARGET_NOT_EXIST);
        DepartmentTarget deleteDepartmentTarget = new DepartmentTarget();
        deleteDepartmentTarget.setId(entity.getId());
        deleteDepartmentTarget.setIsDelete(1);
        return baseMapper.updateById(deleteDepartmentTarget);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Integer updateTarget(DepartmentTargetDTO departmentTargetDTO) {
        DepartmentTarget entity = baseMapper.selectById(departmentTargetDTO.getId());
        BusinessAssert.notNull(entity, McnErrorCode.DEPARTMENT_TARGET_NOT_EXIST);
        DepartmentTarget updateDepartmentTarget = new DepartmentTarget();
        updateDepartmentTarget.setId(entity.getId());
        updateDepartmentTarget.setTargetAmount(departmentTargetDTO.getTargetAmount());
        return baseMapper.updateById(updateDepartmentTarget);
    }

    @Override
    public List<DepartmentTargetListVO> targetList(DepartmentTargetSearchDTO dto) {
        if (StrUtil.isBlank(dto.getQuarterCode())) {
            throw new BusinessException(McnErrorCode.PLEASE_CHOOSE_QUARTER_CODE);
        }
        /**
         * 获取所有商务部门
         */
        List<SDepartment> sDepartments = privilegeClient.getBusinessDepartment().getObj();
        Map<Long, SDepartment> departmentNameMap = sDepartments.stream().collect(Collectors.toMap(SDepartment::getDepartmentId, a -> a));

        /**
         * 获取部门负责人信息
         */
        List<Long> departmentHeadIds = sDepartments.stream().map(SDepartment::getDepartmentHeadId).collect(Collectors.toList());
        List<SUserVo> departmentHeaders = privilegeClient.getDepartmentByUserIds(departmentHeadIds).getObj();
        Map<Long, String> userNameMap = departmentHeaders.stream().collect(Collectors.toMap(SUserVo::getUserId, SUserVo::getUsername));

        List<Long> departmentIds = sDepartments.stream().map(SDepartment::getDepartmentId).collect(Collectors.toList());
        dto.setAlias("c.");
        dto.setDepartmentIds(departmentIds);
        List<DepartmentTargetListVO> departmentTargetList = baseMapper.targetList(dto);
        if (CollectionUtil.isNotEmpty(departmentTargetList)) {
            for (DepartmentTargetListVO departmentTarget : departmentTargetList) {
                Long targetDepartmentId = departmentTarget.getTargetDepartmentId();
                if (departmentNameMap.containsKey(targetDepartmentId)) {
                    departmentTarget.setTargetDepartmentName(departmentNameMap.get(targetDepartmentId).getDepartmentName());
                    departmentTarget.setDepartmentHeadId(departmentNameMap.get(targetDepartmentId).getDepartmentHeadId());
                }
                if (userNameMap.containsKey(departmentTarget.getDepartmentHeadId())) {
                    departmentTarget.setDepartmentHeadName(userNameMap.get(departmentTarget.getDepartmentHeadId()));
                }
            }
        }
        return departmentTargetList;
    }

    @Override
    public void updateQuarterSales() {
        /** 更新部门目标的季度销售金额
         * 取收入合同的创建时间在该季度时间范围内， 并且由该部门成员创建，
         * 单据状态为【审批通过、审批中】状态的所有收入合同的【商务确认合同金额】总和，作为季度销售额保存落库
         */
        /**
         * 获取所有商务部门
         */
        List<SDepartment> sDepartments = privilegeClient.getBusinessDepartment().getObj();
        List<Long> departmentIds = sDepartments.stream().map(SDepartment::getDepartmentId).collect(Collectors.toList());
        baseMapper.updateQuarterSales(departmentIds);

        /**
         * 更新目标达成率=季度销售额/目标金额
         */
        baseMapper.updateTargetReachRate();
    }

    @Override
    public Page<DepartmentTargetPageVO> targetPage(McnPage<DepartmentTargetPageVO> mcnPage, DepartmentTargetSearchDTO dto) {
        if (dto.getTargetDepartmentId() == null) {
            throw new BusinessException(McnErrorCode.PARAM_ERROR);
        }
        dto.setAlias("c.");
        return baseMapper.targetPage(mcnPage, dto);
    }

    @Override
    public List<DepartmentTargetDetailVO> detailByQuarter(String quarterCode) {
        if (StrUtil.isBlank(quarterCode)) {
            throw new BusinessException(McnErrorCode.PLEASE_CHOOSE_QUARTER_CODE);
        }
        List<SDepartment> businessDepartments = privilegeClient.getBusinessDepartment().getObj();
        List<Long> departmentIds = businessDepartments.stream().map(SDepartment::getDepartmentId).collect(Collectors.toList());
        List<DepartmentTarget> departmentTargets = baseMapper.selectList(Wrappers.lambdaQuery(DepartmentTarget.class)
                .eq(DepartmentTarget::getQuarterCode, quarterCode)
                .in(DepartmentTarget::getTargetDepartmentId, departmentIds)
                .eq(DepartmentTarget::getIsDelete, Boolean.FALSE));
        Map<Long, BigDecimal> targetAmountMap = new HashMap<>(16);
        if (CollectionUtil.isNotEmpty(departmentTargets)) {
            targetAmountMap = departmentTargets.stream().collect(Collectors.toMap(DepartmentTarget::getTargetDepartmentId, DepartmentTarget::getTargetAmount));
        }
        List<DepartmentTargetDetailVO> departmentTargetDetailList = new ArrayList<>();
        for (SDepartment businessDepartment : businessDepartments) {
            Long departmentId = businessDepartment.getDepartmentId();
            DepartmentTargetDetailVO departmentTargetDetail = new DepartmentTargetDetailVO();
            departmentTargetDetail.setDepartmentId(departmentId);
            departmentTargetDetail.setDepartmentName(businessDepartment.getDepartmentName());
            if (targetAmountMap.containsKey(businessDepartment.getDepartmentId())) {
                departmentTargetDetail.setTargetAmount(targetAmountMap.get(departmentId));
            }
            departmentTargetDetailList.add(departmentTargetDetail);
        }
        return departmentTargetDetailList;
    }

    private void verifyInsertParam(List<DepartmentTargetDTO> departmentTargetList) {
        if (CollectionUtil.isEmpty(departmentTargetList)) {
            throw new BusinessException(McnErrorCode.PARAM_ERROR);
        }
        departmentTargetList.forEach(d -> {
            boolean paramError = d.getTargetDepartmentId() == null
                    || d.getTargetAmount() == null || StrUtil.isBlank(d.getQuarterCode());
            if (paramError) {
                throw new BusinessException(McnErrorCode.PARAM_ERROR);
            }
        });
    }

    private void verifyTargetCount(List<DepartmentTargetDTO> departmentTargetList) {
        for (DepartmentTargetDTO departmentTargetDTO : departmentTargetList) {
            LambdaQueryWrapper<DepartmentTarget> queryWrapper = Wrappers.lambdaQuery(DepartmentTarget.class)
                    .eq(DepartmentTarget::getQuarterCode, departmentTargetDTO.getQuarterCode())
                    .eq(DepartmentTarget::getTargetDepartmentId, departmentTargetDTO.getTargetDepartmentId())
                    .eq(DepartmentTarget::getIsDelete, Boolean.FALSE);
            Integer existCount = baseMapper.selectCount(queryWrapper);
            if (existCount > 0) {
                throw new BusinessException(McnErrorCode.DEPARTMENT_TARGET_EXIST);
            }
        }
    }
}
